package com.seedwill.common.util;

import java.lang.reflect.Field;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.beanutils.converters.ClassConverter;

import com.seedwill.common.converter.StringConverter;
import com.seedwill.common.converter.TimestampConverter;

public class SimpleBeanUtil {
	public static boolean EMPTY_AS_NULL = true;
	private static final Long defaultLong = null; 
	private static List<String> skipProperties = null;
    /**
     * 注册转换的工具类 使得From中的string --
     * Model中的对应的类型(Date,BigDecimal,Timestamp,Double...)
     */
    static {
    	ConvertUtils.register(new TimestampConverter(), java.sql.Timestamp.class);
        ConvertUtils.register(new ClassConverter(), Double.class);
//        ConvertUtils.register(new LongConverter(defaultLong), Long.class);
//        ConvertUtils.register(new IntegerConverter(defaultLong), Integer.class);
//        ConvertUtils.register(new TimestampConverter(), Timestamp.class);
//        ConvertUtils.register(new BigDecimalConverter(defaultLong), BigDecimal.class);
        ConvertUtils.register(new org.apache.commons.beanutils.converters.BigIntegerConverter(), BigInteger.class);
        //ConvertUtils.register(new org.apache.commons.beanutils.converters.BooleanArrayConverter(), Boolean[].class);
        ConvertUtils.register(new org.apache.commons.beanutils.converters.BooleanConverter(), Boolean.class);
        //ConvertUtils.register(new org.apache.commons.beanutils.converters.ByteArrayConverter(), Byte[].class);
        ConvertUtils.register(new org.apache.commons.beanutils.converters.ByteConverter(), Byte.class);
        //ConvertUtils.register(new org.apache.commons.beanutils.converters.CharacterArrayConverter(), Character[].class);
        ConvertUtils.register(new org.apache.commons.beanutils.converters.CharacterConverter(), Character.class);
        //ConvertUtils.register(new org.apache.commons.beanutils.converters.DoubleArrayConverter(), Double[].class);
        ConvertUtils.register(new org.apache.commons.beanutils.converters.DoubleConverter(), Double.class);
        //ConvertUtils.register(new org.apache.commons.beanutils.converters.FileConverter(), java.io.File.class);
        //ConvertUtils.register(new org.apache.commons.beanutils.converters.FloatArrayConverter(), Float[].class);
        ConvertUtils.register(new org.apache.commons.beanutils.converters.FloatConverter(), Float.class);
        //ConvertUtils.register(new org.apache.commons.beanutils.converters.LongArrayConverter(), Long[].class);
        ConvertUtils.register(new org.apache.commons.beanutils.converters.LongConverter(defaultLong), Long.class);
        //ConvertUtils.register(new org.apache.commons.beanutils.converters.ShortArrayConverter(), Short[].class);
        ConvertUtils.register(new org.apache.commons.beanutils.converters.ShortConverter(), Short.class);
        //ConvertUtils.register(new org.apache.commons.beanutils.converters.IntegerArrayConverter(), Integer[].class);
        ConvertUtils.register(new org.apache.commons.beanutils.converters.IntegerConverter(), Integer.class);
        ConvertUtils.register(new org.apache.commons.beanutils.converters.SqlDateConverter(), java.sql.Date.class);
        ConvertUtils.register(new org.apache.commons.beanutils.converters.SqlTimeConverter(), java.sql.Time.class);
        //ConvertUtils.register(new org.apache.commons.beanutils.converters.SqlTimestampConverter(), java.sql.Timestamp.class);
        //ConvertUtils.register(new org.apache.commons.beanutils.converters.StringArrayConverter(), String[].class);
        ConvertUtils.register(new org.apache.commons.beanutils.converters.StringConverter(), String.class);
        ConvertUtils.register(new StringConverter(), java.sql.Clob.class);
        ConvertUtils.register(new org.apache.commons.beanutils.converters.URLConverter(), java.net.URL.class);
        
		if(skipProperties == null){
			skipProperties = new ArrayList<String>();
			skipProperties.add("serialVersionUID");
		}
    }
    
    public static Object populateProp(Class entityType, String propName, String propValue){
    	Object value = null;
    	if(propValue == null){
    		return value;
    	}
    	try {
			value = ConvertUtils.convert(propValue, entityType.getDeclaredField(propName).getType());
		} catch (SecurityException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (NoSuchFieldException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
    	return value;
    }
    
    public static Object populateProp(Class propType, String propValue){
    	Object value = null;
    	if(propValue == null){
    		return value;
    	}
    	try {
			value = ConvertUtils.convert(propValue, propType);
		} catch (SecurityException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
    	return value;
    }
    
    public static Object populateProp(int propJdbcType,int len, int pric, String propValue){
    	Object value = null;
    	if(propValue == null){
    		return value;
    	}
    	try {
			value = ConvertUtils.convert(propValue, jdbcTypeToNormalJavaType(propJdbcType, len, pric));
		} catch (SecurityException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
    	return value;
    }
    
    public static Class jdbcTypeToNormalJavaType(int propJdbcType, int len, int pric) {
    		Class ctype = null;
    		switch(propJdbcType){
    		case java.sql.Types.CHAR:
    		case java.sql.Types.VARCHAR:
    		case java.sql.Types.LONGVARCHAR:
    			ctype = String.class;
    			break;
    		
    		case java.sql.Types.NUMERIC:
    		case java.sql.Types.DECIMAL:
    			if(len>=19){
    				if(pric>0){
    					ctype = java.math.BigDecimal.class;
    				}else{
    					ctype = java.math.BigInteger.class;
    				}
    			}else{
    				if(pric>0){
    					ctype = Double.class;
    				}else{
    					ctype = Integer.class;
    				}
    			}
    			break;
    		case java.sql.Types.BIT:
    		case java.sql.Types.BOOLEAN:
    			ctype = Boolean.class;
    			break;	
    		case java.sql.Types.TINYINT:
    			ctype = Byte.class;
    			break;
    		case java.sql.Types.SMALLINT:
    			ctype = Short.class;
    			break;
    		case java.sql.Types.INTEGER:
    			ctype = Integer.class;
    			break;
    		case java.sql.Types.BIGINT:
    			ctype = Long.class;
    			break;   			
    		case java.sql.Types.REAL:
    			ctype = Float.class;
    			break; 	
    		case java.sql.Types.FLOAT:
    		case java.sql.Types.DOUBLE:
    			ctype = Double.class;
    			break;
    		case java.sql.Types.BLOB:
    		case java.sql.Types.BINARY:
    		case java.sql.Types.VARBINARY:
    		case java.sql.Types.LONGVARBINARY:
    			//byte[]
    			ctype = java.sql.Blob.class;
    			break;		
    		case java.sql.Types.DATE:
    			ctype = java.util.Date.class;
    			break;
    		case java.sql.Types.TIMESTAMP:
    			ctype = java.sql.Timestamp.class;
    			break;
    		case java.sql.Types.TIME:
    			ctype = java.sql.Time.class;
    			break;  
    		case java.sql.Types.CLOB:
    			ctype = java.sql.Clob.class;
    			break;	    			
    			
    		case java.sql.Types.ARRAY:
    			ctype = java.sql.Array.class;
    			break;
    		case java.sql.Types.STRUCT:
    			ctype = java.sql.Struct.class;
    			break;	
    		case java.sql.Types.REF:
    			ctype = java.sql.Ref.class;
    			break;	
    		case java.sql.Types.DATALINK:
    			ctype = java.net.URL.class;
    			break;	
    		case java.sql.Types.JAVA_OBJECT:
    		case java.sql.Types.DISTINCT:
    			ctype = Object.class;
    			break;	
    		
     
    		default:
    			ctype = java.lang.Object.class;
    			break;
    		}
    		return ctype;
	}

	public static Object populate(Class entityType, Map paraMap){
		return populate(entityType, paraMap, null);
    }
    public static Object populate(Class entityType, Map paraMap, String entityPrefix){
    	if(entityPrefix == null){
    		entityPrefix = "";
    	}
		Object obj = null;
		Field[] flds = entityType.getDeclaredFields();
		Map map = null;
		if(flds!=null && flds.length>0){
			try {
				obj = entityType.newInstance();
			} catch (InstantiationException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			for(Field fld : flds){
				//skip
				if(!skipProperties.contains(fld.getName())){
					String paraName = fld.getName();
					if(paraMap.containsKey(entityPrefix+paraName)){
						String propValue = null;
						Object reqValue = paraMap.get(entityPrefix+paraName);
						if(reqValue instanceof String){
							propValue = (String) reqValue;
						}else if(reqValue instanceof String[]){
							propValue = ((String[]) reqValue)[0];
						}else{
							//skip
						}
						if(EMPTY_AS_NULL && propValue!=null && propValue.trim().length()==0){
							propValue = null;
						}
						if(propValue != null){
							Object value = ConvertUtils.convert(propValue, fld.getType());
							if(value != null){
								OgnlHelper.pushValueDirectly(obj, paraName, value);
							}
						}
						
						
					}
				}
			}
		}
		return obj;
    }
}
